/**
 * Writed by yura and mak
 */

package wz.legend.handlers.steps;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import wz.legend.Context;
import wz.legend.HttpContext;
import wz.legend.Status;


public class StepMachineImpl implements StepMachine {
    private List<Step> steps = new ArrayList<Step>();
    private int stepIndex;
    private long lastExecuteTime;
    private long timeoutStepStart = 6000;

    public StepMachineImpl() {
        stepIndex = 0;
    }

    public StepMachineImpl(Collection<Step> steps) {
        this();
        this.steps.addAll(steps);
    }

    public synchronized void handle(HttpContext httpContext, Context context) {
        Step step = getCurrentStep();
        if (step != null) {
            synchronized (this) {
                step.handle(httpContext, context);
                if (step.getState() == State.UNKNOWN
                        || (lastExecuteTime + timeoutStepStart <= System
                                .currentTimeMillis() && step.getState() == State.START)) {
                    step.execute(context);
                    lastExecuteTime = System.currentTimeMillis();
                } else if (step.getState() == State.STOPED) {
                    step.reset();
                    stepIndex++;
                } else if (step.getState() == State.GOBACK) {
                    step.reset();
                    stepIndex--;
                }
            }
        }
    }

    private Step getCurrentStep() {
        if (!isDone())
            return steps.get(stepIndex);
        else
            return null;
    }

    public boolean isDone() {
        return stepIndex >= steps.size();
    }

    public void reset() {
        stepIndex = 0;
        for (Step step : steps) {
            step.reset();
        }
    }

    public long getTimeoutStepStart() {
        return timeoutStepStart;
    }

    public void setTimeoutStepStart(long timeoutStepStart) {
        this.timeoutStepStart = timeoutStepStart;
    }

    public List<Step> getSteps() {
        return steps;
    }

    public void setSteps(List<Step> steps) {
        this.steps = steps;
    }
}
